﻿// CustomAuthStateProvider.cs
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
using System.Text.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Threading.Tasks;
public class CustomAuthStateProvider : AuthenticationStateProvider
{
    private readonly ILocalStorageService _localStorage; // 注入 LocalStorage
    private ClaimsPrincipal _user = new ClaimsPrincipal(new ClaimsIdentity());

    public CustomAuthStateProvider(ILocalStorageService localStorage)
    {
        _localStorage = localStorage; // 初始化 LocalStorage
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var token = await _localStorage.GetItemAsync<string>("jwtToken");
        if (!string.IsNullOrEmpty(token) && IsTokenValid(token))
        {
            var identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
            _user = new ClaimsPrincipal(identity);
        }
        else
        {
            _user = new ClaimsPrincipal(new ClaimsIdentity());
        }

        return new AuthenticationState(_user);
    }
    /// <summary>
    /// 调用 NotifyAuthenticationStateChanged 方法通知所有订阅者（如 AuthorizeRouteView）用户的认证状态已更改
    /// </summary>
    /// <param name="token"></param>
    public void MarkUserAsAuthenticated(string token)
    {
        var identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
        _user = new ClaimsPrincipal(identity);
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }

    public void MarkUserAsLoggedOut()
    {
        _user = new ClaimsPrincipal(new ClaimsIdentity());
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }


    private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
    {
        try
        {
            if (string.IsNullOrEmpty(jwt))
            {
                throw new ArgumentException("JWT token is null or empty.");
            }

            // Split the JWT into its three parts: Header, Payload, Signature
            var parts = jwt.Split('.');

            if (parts.Length != 3)
            {
                throw new FormatException("Invalid JWT token format.");
            }

            // Decode the payload part (Base64Url encoded)
            /*
             * 原始代码中，JWT 的 payload 部分是 Base64Url 编码的
             * 而标准的 Base64 解码无法直接处理这种编码格式。
             */
            var base64UrlPayload = parts[1];
            // Convert Base64Url 2 Base64
            var base64Payload = Base64UrlDecode(base64UrlPayload);

            // Convert the decoded payload to JSON and deserialize it
            var jsonBytes = Convert.FromBase64String(base64Payload);
            var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);

            return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()));
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error parsing JWT token: {ex.Message}");
            return Enumerable.Empty<Claim>();
        }
    }

    private string Base64UrlDecode(string base64Url)
    {
        // Replace URL-safe characters with standard Base64 characters
        var padded = base64Url.Replace('-', '+').Replace('_', '/');

        // Add padding characters if necessary
        switch (padded.Length % 4)
        {
            case 2:
                padded += "==";
                break;
            case 3:
                padded += "=";
                break;
        }

        return padded;
    }
    private bool IsTokenValid(string token)
    {
        try
        {
            var handler = new JwtSecurityTokenHandler();
            var jwtToken = handler.ReadJwtToken(token);

            // 检查 Token 是否过期
            if (jwtToken.ValidTo < DateTime.UtcNow)
            {
                return false;
            }

            return true;
        }
        catch
        {
            return false;
        }
    }
}